import config from '../config/index.js'
import store from '@/store/auth.js'
import Vue from 'vue'
import globalState from '@/utils/globalState.js'

// 标记是否正在进行登录操作，防止重复调用
let isRefreshing = false
// 避免多次跳转到登录页面
let hasRedirectedToLogin = false
// 最大自动登录尝试次数
let autoLoginAttempts = 0
const MAX_AUTO_LOGIN_ATTEMPTS = 3
// 记录上次登录时间，避免频繁登录
let lastLoginTime = 0
// 登录防抖时间(毫秒)
const LOGIN_DEBOUNCE_TIME = 3000
// 是否是手动登录的标志
let isManualLogin = false  // 全局变量，不使用window
// 用户信息请求失败计数器
let userInfoFailCount = 0
const MAX_USER_INFO_FAIL = 3

// 创建全局事件总线
if (!Vue.prototype.$bus) {
  Vue.prototype.$bus = new Vue()
}

// 调试函数，检查token状态
function debugTokenStatus(prefix = '') {
  const token = uni.getStorageSync('token')
  const storeToken = store.state.token
  const userInfo = uni.getStorageSync('userInfo')
  
  console.log(`${prefix} TOKEN状态:`, { 
    storageToken: token ? `${token.substring(0, 10)}...` : '空',
    vuexToken: storeToken ? `${storeToken.substring(0, 10)}...` : '空',
    hasUserInfo: !!userInfo,
    headerWouldBe: token ? `Bearer ${token.substring(0, 10)}...` : '无Authorization头'
  })
  
  return !!token
}

/**
 * 创建通用请求方法
 * @description 用于处理普通的API请求
 */
const request = (options) => {
  return new Promise((resolve, reject) => {
    // 使用函数获取token，确保每次都是最新的
    const getToken = () => uni.getStorageSync('token');
    
    // 记录初始token状态（仅用于调试）
    const initialToken = getToken();
    debugTokenStatus('【创建请求】');
    
    // 构建请求头
    const header = {
      ...options.header
    }
    
    // 发起请求并处理响应
    const makeRequest = () => {
      // 获取当前最新token
      const currentToken = getToken();
      
      // 构建请求URL
      let url = config.baseURL + options.url;
      if (options.params) {
        const queryString = Object.entries(options.params)
          .map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`)
          .join('&');
        url = `${url}?${queryString}`;
      }
      
      // 添加Authorization头
      if (currentToken) {
        console.log('添加Authorization头:', currentToken.substring(0, 10) + '...')
        header.Authorization = `Bearer ${currentToken}`
      } else {
        console.error('请求时token为空，无法添加Authorization头')
        delete header.Authorization; // 确保移除可能存在的旧Authorization头
      }
      
      // 打印完整的请求信息用于调试
      console.log(`发起请求: ${options.method || 'GET'} ${url}`, {
        headers: JSON.stringify(header),
        hasAuth: !!header.Authorization,
        tokenLength: header.Authorization ? header.Authorization.length : 0
      })
      
      // 调试：检查token状态
      debugTokenStatus('【发送请求前】');
      
      // 再次检查token（可能在请求过程中已更新）
      const currentTokenAgain = uni.getStorageSync('token')
      
      if (currentTokenAgain && currentTokenAgain !== currentToken) {
        console.log('请求过程中token已更新，使用新token')
        header.Authorization = `Bearer ${currentTokenAgain}`
      }
      
      // 发起请求并处理响应
      uni.request({
        url,
        data: options.data,
        method: options.method,
        header,
        success: (res) => {
          console.log(`API响应[${url}]:`, res.statusCode)
          
          if (res.statusCode === 401 || res.statusCode === 403) {
            debugTokenStatus('【收到401/403】');
            console.log('认证失败(401/403)，尝试重新登录')
            
            // 如果已经在刷新token，直接返回错误
            if (isRefreshing) {
              console.log('已有登录请求在进行中，本次请求取消')
              reject(new Error('登录中，请稍后再试'))
              return
            }
            
            // 检查是否在防抖时间内
            const now = Date.now()
            // 同时检查全局变量和本地存储
            const isManual = globalState.getManualLogin() || uni.getStorageSync('isManualLogin');
            if (!isManual && now - lastLoginTime < LOGIN_DEBOUNCE_TIME) {
              console.log('登录请求太频繁，取消本次请求')
              reject(new Error('请求频繁，请稍后再试'))
              return
            }
            
            // 重置手动登录标志
            globalState.setManualLogin(false)
            // 清除存储的标志
            uni.removeStorageSync('isManualLogin')
            
            // 登录成功后重置时间，不再触发防抖
            lastLoginTime = 0
            
            isRefreshing = true
            
            // 如果认证失败，清除token
            uni.removeStorageSync('token')
            uni.removeStorageSync('userInfo')
            
            // 检查是否可能处于循环登录状态
            if (now - lastLoginTime < 5000) { // 5秒内发生多次登录尝试
              userInfoFailCount++;
              console.log(`短时间内多次认证失败，计数: ${userInfoFailCount}/${MAX_USER_INFO_FAIL}`);
              
              if (userInfoFailCount >= MAX_USER_INFO_FAIL) {
                console.error('检测到认证循环，强制重置认证状态');
                resetAuthState();
                
                // 提示用户
                uni.showToast({
                  title: '登录异常，请手动登录',
                  icon: 'none',
                  duration: 2000
                });
                
                // 延迟跳转到登录页
                setTimeout(() => {
                  uni.navigateTo({ url: '/pages/login/login' });
                }, 1500);
                
                reject(new Error('检测到认证循环，已重置状态'));
                return;
              }
            } else {
              // 重置计数器
              userInfoFailCount = 0;
            }
            
            // 检查是否超过最大自动登录尝试次数
            if (autoLoginAttempts >= MAX_AUTO_LOGIN_ATTEMPTS) {
              console.log('超过最大自动登录尝试次数，需手动登录')
              handleUnauthenticated()
              reject(new Error('多次自动登录失败，请手动登录'))
              return
            }
            
            // 增加自动登录尝试次数
            autoLoginAttempts++
            console.log(`尝试自动登录 (${autoLoginAttempts}/${MAX_AUTO_LOGIN_ATTEMPTS})`)
            
            // 尝试自动重新登录
            store.dispatch('wxLogin').then(success => {
              console.log('自动重新登录结果:', success)
              isRefreshing = false
              
              if (success) {
                // 自动登录成功，重置尝试次数
                autoLoginAttempts = 0
                // 完全重置登录时间限制
                lastLoginTime = 0
                // 重置用户信息失败计数
                userInfoFailCount = 0
                
                // 登录后获取用户信息，同步存储
                store.dispatch('fetchUserInfo').then(userInfo => {
                  console.log('重新登录后成功获取用户信息:', userInfo);
                  
                  // 触发全局登录成功事件
                  Vue.prototype.$bus.$emit('auth:login-success', {
                    refreshToken: true,
                    userInfo: userInfo
                  });
                  
                  console.log('登录成功，触发页面刷新');
                  
                  // 不需要在这里直接刷新页面，因为已经触发了auth:login-success事件
                  // 页面会通过监听该事件来刷新
                  console.log('通过事件机制触发页面刷新');
                  
                  // 不重试当前失败的请求，因为页面会重新加载所有数据
                  // 直接返回一个成功结果给当前请求，避免等待超时
                  resolve({
                    success: true,
                    message: '已重新登录，页面将刷新',
                    data: null
                  });
                }).catch(err => {
                  console.error('重新登录后获取用户信息失败:', err);
                  
                  // 即使获取用户信息失败，也尝试使用新token继续请求
                  console.log('尽管获取用户信息失败，仍尝试继续请求');
                  setTimeout(() => {
                    makeRequest();
                  }, 300);
                });
              } else {
                // 如果是最后一次尝试且失败
                if (autoLoginAttempts >= MAX_AUTO_LOGIN_ATTEMPTS) {
                  handleUnauthenticated()
                } else {
                  // 登录失败但未达到最大尝试次数，只提示但不跳转
                  console.log('自动登录失败，继续尝试...')
                }
                reject(new Error('自动登录失败'))
              }
            }).catch(error => {
              console.error('自动登录失败:', error)
              isRefreshing = false
              
              // 统一处理未认证情况
              handleUnauthenticated()
              
              reject(error)
            })
            
            return
          }
          
          if (res.statusCode === 200) {
            const result = res.data;
            if (result.success) {
              resolve(result);
            } else {
              // 请求成功但业务失败的情况
              reject(new Error(result.message || '请求失败'));
            }
          } else {
            console.log('API请求失败:', res.data)
            reject(new Error(res.data?.message || `请求失败(${res.statusCode})`))
          }
        },
        fail: (err) => {
          console.error('网络请求失败:', err)
          reject(err)
        }
      })
    }
    
    // 发起请求
    makeRequest()
  })
}

/**
 * 创建图片专用请求方法
 * @description 用于处理图片相关的请求
 */
export const imageRequest = {
  get(url, options = {}) {
    return new Promise((resolve, reject) => {
      uni.request({
        url,
        method: 'GET',
        header: {
          'Authorization': 'Bearer ' + uni.getStorageSync('token')
        },
        responseType: options.responseType || 'text',
        success: (res) => {
          if (res.statusCode === 200) {
            resolve(res);
          } else {
            reject(new Error(`请求失败: ${res.statusCode}`));
          }
        },
        fail: reject
      });
    });
  }
};

/**
 * 处理未认证的情况
 */
function handleUnauthenticated() {
  // 重置尝试次数
  autoLoginAttempts = 0
  
  if (hasRedirectedToLogin) return
  
  hasRedirectedToLogin = true
  console.log('跳转到登录页')
  
  // 显示更友好的提示 
  uni.showToast({
    title: '请登录继续使用',
    icon: 'none',
    duration: 1500
  })
  
  setTimeout(() => {
    uni.navigateTo({
      url: '/pages/login/login'
    })
    // 5秒后重置标志位，允许再次跳转
    setTimeout(() => {
      hasRedirectedToLogin = false
    }, 5000)
  }, 800) // 缩短等待时间
}

/**
 * 完全重置认证状态
 * 用于解决循环登录问题
 */
function resetAuthState() {
  console.log('完全重置认证状态');
  // 清除所有状态变量
  isRefreshing = false;
  hasRedirectedToLogin = false;
  autoLoginAttempts = 0;
  lastLoginTime = 0; 
  userInfoFailCount = 0;
  
  // 清除storage中的认证相关数据
  uni.removeStorageSync('token');
  uni.removeStorageSync('userInfo');
  uni.removeStorageSync('isLogin');
  uni.removeStorageSync('isManualLogin');
  
  // 清除vuex状态
  store.dispatch('clearAuth');
  
  console.log('认证状态已完全重置');
}

export default request 